home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / pc / SATAN11.ZIP / SRC / PORT_SCA / TCP_SCAN.C < prev    next >
Encoding:
C/C++ Source or Header  |  1995-04-04  |  14.3 KB  |  590 lines

  1.  /*
  2.   * tcp_scan - determine available tcp services, optionally collect banners
  3.   * and detect telnet options
  4.   * 
  5.   * Author: Wietse Venema.
  6.   */
  7.  
  8. #include <sys/types.h>
  9. #include <sys/param.h>
  10. #include <sys/time.h>
  11. #include <sys/socket.h>
  12.  
  13. #include <netinet/in.h>
  14. #include <netinet/in_systm.h>
  15. #include <netinet/ip.h>
  16. #include <netinet/ip_icmp.h>
  17. #include <netinet/tcp.h>
  18.  
  19. #include <arpa/telnet.h>
  20.  
  21. #include <stdio.h>
  22. #include <signal.h>
  23. #include <netdb.h>
  24. #include <string.h>
  25. #include <errno.h>
  26.  
  27. extern int errno;
  28. extern char *optarg;
  29. extern int optind;
  30.  
  31. #ifndef __STDC__
  32. extern char *strerror();
  33. #endif
  34.  
  35. #define offsetof(t,m)    (size_t)(&(((t *)0)->m))
  36.  
  37. #ifndef IPPORT_TELNET
  38. #define IPPORT_TELNET    23
  39. #endif
  40.  
  41. #ifndef FD_SET
  42. #include <sys/select.h>
  43. #endif
  44.  
  45. #include "lib.h"
  46.  
  47. #define BANNER_LENGTH    2048        /* upper bound on banner info */
  48. #define BANNER_TIME    10        /* time for host to send banner */
  49. #define BANNER_IDLE    1        /* delay after last banner info */
  50.  
  51. #define YES     1
  52. #define NO      0
  53.  
  54. #define WAIT    1
  55. #define NOWAIT    0
  56.  
  57. int     verbose;            /* default silent mode */
  58. int     banner_time = BANNER_TIME;    /* banner timeout */
  59. int     open_file_limit;        /* max nr of open files */
  60. int     load_limit;            /* max nr of open sockets */
  61.  
  62. struct timeval now;            /* banner_info last update time */
  63. fd_set  write_socket_mask;        /* sockets with connect() in progress */
  64. fd_set  read_socket_mask;        /* sockets with connect() finished */
  65. int     ports_busy;            /* number of open sockets */
  66. int     ports_done;            /* number of finished sockets */
  67. int     max_sock;            /* max socket file descriptor */
  68. int     want_err;            /* want good/bad news */
  69. int     show_all;            /* report all ports */
  70.  
  71. int    *socket_to_port;            /* socket to port number */
  72.  
  73. typedef struct {
  74.     unsigned char *buf;            /* banner information or null */
  75.     int     count;            /* amount of banner received sofar */
  76.     int     flags;            /* see below */
  77.     struct timeval connect_time;    /* when connect() finished */
  78.     struct timeval read_time;        /* time of last banner update */
  79. } BANNER_INFO;
  80.  
  81. BANNER_INFO *banner_info = 0;
  82.  
  83. #define F_TELNET    (1<<0)        /* telnet options seen */
  84.  
  85. int     icmp_sock;            /* for unreachable reports */
  86. static struct sockaddr_in sin;        /* remote endpoint info */
  87.  
  88. static char *send_string;        /* string to send */
  89. int response_time;            /* need some response */
  90.  
  91. #define NEW(type, count) (type *) mymalloc((count) * sizeof(type))
  92.  
  93. #define time_since(t) (now.tv_sec - t.tv_sec + 1e-6 * (now.tv_usec - t.tv_usec))
  94.  
  95. /* main - command-line interface */
  96.  
  97. main(argc, argv)
  98. int     argc;
  99. char   *argv[];
  100. {
  101.     int     c;
  102.     struct protoent *pe;
  103.     char  **ports;
  104.  
  105.     progname = argv[0];
  106.     if (geteuid())
  107.     error("This program needs root privileges");
  108.  
  109.     open_file_limit = open_limit();
  110.     load_limit = open_file_limit - 10;
  111.  
  112.     while ((c = getopt(argc, argv, "abl:s:t:uUvw:")) != EOF) {
  113.     switch (c) {
  114.     case 'a':
  115.         show_all = 1;
  116.         break;
  117.     case 'b':
  118.         if (banner_info == 0)
  119.         banner_info = NEW(BANNER_INFO, open_file_limit);
  120.         break;
  121.     case 'l':
  122.         if ((load_limit = atoi(optarg)) <= 0)
  123.         usage("invalid load limit");
  124.         if (load_limit > open_file_limit - 10)
  125.         load_limit = open_file_limit - 10;
  126.         break;
  127.     case 's':
  128.         send_string = optarg;
  129.         signal(SIGPIPE, SIG_IGN);
  130.         break;
  131.      case 't':
  132.         if ((response_time = atoi(optarg)) <= 0)
  133.         usage("invalid timeout");
  134.         break;
  135.     case 'u':
  136.         want_err = EHOSTUNREACH;
  137.         break;
  138.     case 'U':
  139.         want_err = ~EHOSTUNREACH;
  140.         break;
  141.     case 'v':
  142.         verbose = 1;
  143.         break;
  144.     case 'w':
  145.         if ((banner_time = atoi(optarg)) <= 0)
  146.         usage("invalid timeout");
  147.         break;
  148.     default:
  149.         usage((char *) 0);
  150.         break;
  151.     }
  152.     }
  153.     argc -= (optind - 1);
  154.     argv += (optind - 1);
  155.     if (argc < 3)
  156.     usage("missing host or service argument");
  157.  
  158.     socket_to_port = NEW(int, open_file_limit);
  159.  
  160.     FD_ZERO(&write_socket_mask);
  161.     FD_ZERO(&read_socket_mask);
  162.     ports_busy = 0;
  163.  
  164.     /*
  165.      * Allocate the socket to read ICMP replies.
  166.      */
  167.     if ((pe = getprotobyname("icmp")) == 0)
  168.     error("icmp: unknown protocol");
  169.     if ((icmp_sock = socket(AF_INET, SOCK_RAW, pe->p_proto)) < 0)
  170.     error("icmp socket: %m");
  171.     FD_SET(icmp_sock, &read_socket_mask);
  172.  
  173.     /*
  174.      * Scan the ports.
  175.      */
  176.     memset((char *) &sin, 0, sizeof(sin));
  177.     sin.sin_addr = find_addr(argv[1]);
  178.     sin.sin_family = AF_INET;
  179.  
  180.     if (response_time > 0)
  181.     alarm(response_time);
  182.  
  183.     for (ports = argv + 2; *ports; ports++)
  184.     scan_ports(*ports);
  185.     while (ports_busy > 0)
  186.     monitor_ports(WAIT);
  187.  
  188.     return (0);
  189. }
  190.  
  191. /* usage - explain command syntax */
  192.  
  193. usage(why)
  194. char   *why;
  195. {
  196.     if (why)
  197.     remark(why);
  198.     error("usage: %s [-abuU] [-l load] [-w time] host ports...", progname);
  199. }
  200.  
  201. /* scan_ports - scan ranges of ports */
  202.  
  203. scan_ports(service)
  204. char   *service;
  205. {
  206.     char   *cp;
  207.     int     min_port;
  208.     int     max_port;
  209.     int     port;
  210.     int     sock;
  211.  
  212.     /*
  213.      * Translate service argument to range of port numbers.
  214.      */
  215.     if ((cp = strchr(service, '-')) != 0) {
  216.     *cp++ = 0;
  217.     min_port = (service[0] ? ntohs(find_port(service, "tcp")) : 1);
  218.     max_port = (cp[0] ? ntohs(find_port(cp, "tcp")) : 65535);
  219.     } else {
  220.     min_port = max_port = ntohs(find_port(service, "tcp"));
  221.     }
  222.  
  223.     /*
  224.      * Iterate over each port in the given range. Try to keep as many sockets
  225.      * open at the same time as possible. Gradually increase the number of
  226.      * probes so that they will be spread in time.
  227.      */
  228.     for (port = min_port; port <= max_port; port++) {
  229.     if (verbose)
  230.         remark("connecting to port %d", port);
  231.     sin.sin_port = htons(port);
  232.     while ((sock = socket(sin.sin_family, SOCK_STREAM, 0)) < 0) {
  233.         remark("socket: %m");
  234.         monitor_ports(WAIT);
  235.     }
  236.     add_socket(sock, port);
  237.     non_blocking(sock, YES);
  238.     if (connect(sock, (struct sockaddr *) & sin, sizeof(sin)) < 0
  239.         && errno != EINPROGRESS) {
  240.         report_and_drop_socket(sock, errno);
  241.         continue;
  242.     }
  243.     if (ports_busy < load_limit && ports_busy < ports_done) {
  244.         monitor_ports(NOWAIT);
  245.     } else {
  246.         while (ports_busy >= load_limit || ports_busy >= ports_done)
  247.         monitor_ports(WAIT);
  248.     }
  249.     }
  250. }
  251.  
  252. /* monitor_ports - watch for socket activity */
  253.  
  254. monitor_ports(wait)
  255. int     wait;
  256. {
  257.     fd_set  read_mask;
  258.     fd_set  write_mask;
  259.     static struct timeval waitsome = {1, 1,};
  260.     static struct timeval waitnot = {0, 0,};
  261.     int     sock;
  262.     char    ch;
  263.  
  264.     if (banner_info == 0) {
  265.  
  266.     /*
  267.      * When a connect() completes, report the socket and get rid of it.
  268.      */
  269.     write_mask = write_socket_mask;
  270.     read_mask = read_socket_mask;
  271.     if (select(max_sock + 1, &read_mask, &write_mask, (fd_set *) 0,
  272.            wait ? (struct timeval *) 0 : &waitnot) < 0)
  273.         error("select: %m");
  274.     if (FD_ISSET(icmp_sock, &read_mask))
  275.         receive_icmp(icmp_sock);
  276.     for (sock = 0; ports_busy > 0 && sock <= max_sock; sock++) {
  277.         if (FD_ISSET(sock, &write_mask)) {
  278.         if (read(sock, &ch, 1) < 0 && errno != EWOULDBLOCK && errno != EAGAIN) {
  279.             report_and_drop_socket(sock, errno);
  280.         } else {
  281.             report_and_drop_socket(sock, 0);
  282.         }
  283.         }
  284.     }
  285.     } else {
  286.  
  287.     /*
  288.      * When a connect() completes, try to receive some data within
  289.      * banner_time seconds. Assume we have received all banner data when
  290.      * a socket stops sending for BANNER_IDLE seconds.
  291.      */
  292.     write_mask = write_socket_mask;
  293.     read_mask = read_socket_mask;
  294.     if (select(max_sock + 1, &read_mask, &write_mask, (fd_set *) 0,
  295.            wait ? &waitsome : &waitnot) < 0)
  296.         error("select: %m");
  297.     if (FD_ISSET(icmp_sock, &read_mask))
  298.         receive_icmp(icmp_sock);
  299.     gettimeofday(&now, (struct timezone *) 0);
  300.     for (sock = 0; ports_busy > 0 && sock <= max_sock; sock++) {
  301.         if (sock == icmp_sock)
  302.         continue;
  303.         if (FD_ISSET(sock, &write_mask)) {
  304.         FD_CLR(sock, &write_socket_mask);
  305.         FD_SET(sock, &read_socket_mask);
  306.         banner_info[sock].connect_time = now;
  307.         if (send_string)
  308.             do_send_string(sock);
  309.         } else if (FD_ISSET(sock, &read_mask)) {
  310.         switch (read_socket(sock)) {
  311.         case -1:
  312.             if (errno != EWOULDBLOCK && errno != EAGAIN)
  313.             report_and_drop_socket(sock, errno);
  314.             break;
  315.         case 0:
  316.             report_and_drop_socket(sock, 0);
  317.             break;
  318.         }
  319.         } else if (FD_ISSET(sock, &read_socket_mask)) {
  320.         if (time_since_connect(sock) > banner_time
  321.             || time_since_read(sock) > BANNER_IDLE)
  322.             report_and_drop_socket(sock, 0);
  323.         }
  324.     }
  325.     }
  326. }
  327.  
  328. /* read_socket - read data from server */
  329.  
  330. read_socket(sock)
  331. int     sock;
  332. {
  333.     BANNER_INFO *bp = banner_info + sock;
  334.     unsigned char *cp;
  335.     int     len;
  336.     int     count;
  337.  
  338.     if (bp->buf == 0)
  339.     bp->buf = (unsigned char *) mymalloc(BANNER_LENGTH);
  340.     cp = bp->buf + bp->count;
  341.     len = BANNER_LENGTH - bp->count;
  342.  
  343.     if (len == 0)
  344.     return (0);
  345.  
  346.     bp->read_time = now;
  347.  
  348.     /*
  349.      * Process banners with one-character reads so that we can detect telnet
  350.      * options.
  351.      */
  352.  
  353.     if ((count = read(sock, cp, 1)) == 1) {
  354.     if (cp[0] == IAC) {
  355.         if ((count = read(sock, cp + 1, 2)) == 2) {
  356.         if (cp[1] == WILL || cp[1] == WONT) {
  357.             cp[1] = DONT;
  358.             bp->flags |= F_TELNET;
  359.             write(sock, cp, 3);
  360.         } else if (cp[1] == DO || cp[1] == DONT) {
  361.             cp[1] = WONT;
  362.             bp->flags |= F_TELNET;
  363.             write(sock, cp, 3);
  364.         }
  365.         }
  366.     } else {                /* cp[0] != IAC */
  367.         bp->count++;
  368.     }
  369.     }
  370.     return (count);
  371. }
  372.  
  373. /* report_and_drop_socket - report what we know about this service */
  374.  
  375. report_and_drop_socket(sock, err)
  376. int     sock;
  377. int     err;
  378. {
  379.     alarm(0);
  380.  
  381.     if (show_all || want_err == err || (want_err < 0 && want_err != ~err)) {
  382.     struct servent *sp;
  383.     int     port = socket_to_port[sock];
  384.  
  385.     printf("%d:%s:", port, (sp = getservbyport(htons(port), "tcp")) != 0 ?
  386.            sp->s_name : "UNKNOWN");
  387.     if (banner_info) {
  388.         BANNER_INFO *bp = banner_info + sock;
  389.  
  390.         if (bp->flags & F_TELNET)
  391.         putchar('t');
  392.         putchar(':');
  393.         if (bp->count > 0)
  394.         print_data(stdout, bp->buf, bp->count);
  395.     }
  396.     if (err && show_all)
  397.         printf("%s", strerror(err));
  398.     printf("\n");
  399.     fflush(stdout);
  400.     }
  401.     drop_socket(sock);
  402. }
  403.  
  404. /* add_socket - say this socket is being connected */
  405.  
  406. add_socket(sock, port)
  407. int     sock;
  408. int     port;
  409. {
  410.     BANNER_INFO *bp;
  411.  
  412.     socket_to_port[sock] = port;
  413.     if (banner_info) {
  414.     bp = banner_info + sock;
  415.     bp->count = 0;
  416.     bp->buf = 0;
  417.     bp->flags = 0;
  418.     }
  419.     FD_SET(sock, &write_socket_mask);
  420.     if (sock > max_sock)
  421.     max_sock = sock;
  422.     ports_busy++;
  423. }
  424.  
  425. /* drop_socket - release socket resources */
  426.  
  427. drop_socket(sock)
  428. int     sock;
  429. {
  430.     BANNER_INFO *bp;
  431.  
  432.     if (banner_info && (bp = banner_info + sock)->buf)
  433.     free((char *) bp->buf);
  434.     close(sock);
  435.     FD_CLR(sock, &read_socket_mask);
  436.     FD_CLR(sock, &write_socket_mask);
  437.     ports_busy--;
  438.     ports_done++;
  439. }
  440.  
  441. /* time_since_read - how long since read() completed? */
  442.  
  443. time_since_read(sock)
  444. int     sock;
  445. {
  446.     BANNER_INFO *bp = banner_info + sock;
  447.  
  448.     return (bp->count == 0 ? 0 : time_since(bp->read_time));
  449. }
  450.  
  451. /* time_since_connect - how long since connect() completed? */
  452.  
  453. time_since_connect(sock)
  454. int     sock;
  455. {
  456.     BANNER_INFO *bp = banner_info + sock;
  457.  
  458.     return (time_since(bp->connect_time));
  459. }
  460.  
  461. /* receive_icmp - receive and decode ICMP message */
  462.  
  463. receive_icmp(sock)
  464. int     sock;
  465. {
  466.     union {
  467.     char    chars[BUFSIZ];
  468.     struct ip ip;
  469.     }       buf;
  470.     int     data_len;
  471.     int     hdr_len;
  472.     struct ip *ip;
  473.     struct icmp *icmp;
  474.     struct tcphdr *tcp;
  475.     int     port;
  476.  
  477.     if ((data_len = recv(sock, (char *) &buf, sizeof(buf), 0)) < 0) {
  478.     error("error: recv: %m");
  479.     return;
  480.     }
  481.  
  482.     /*
  483.      * Extract the IP header.
  484.      */
  485.     ip = &buf.ip;
  486.     if (ip->ip_p != IPPROTO_ICMP) {
  487.     error("error: not ICMP proto (%d)", ip->ip_p);
  488.     return;
  489.     }
  490.  
  491.     /*
  492.      * Extract the IP payload.
  493.      */
  494.     hdr_len = ip->ip_hl << 2;
  495.     if (data_len - hdr_len < ICMP_MINLEN) {
  496.     remark("short ICMP packet (%d bytes)", data_len);
  497.     return;
  498.     }
  499.     icmp = (struct icmp *) ((char *) ip + hdr_len);
  500.     data_len -= hdr_len;
  501.  
  502.     if (icmp->icmp_type != ICMP_UNREACH)
  503.     return;
  504.  
  505.     /*
  506.      * Extract the offending IP packet header.
  507.      */
  508.     if (data_len < offsetof(struct icmp, icmp_ip) + sizeof(icmp->icmp_ip)) {
  509.     remark("short IP header in ICMP");
  510.     return;
  511.     }
  512.     ip = &(icmp->icmp_ip);
  513.     if (ip->ip_p != IPPROTO_TCP)
  514.     return;
  515.     if (ip->ip_dst.s_addr != sin.sin_addr.s_addr)
  516.     return;
  517.  
  518.     /*
  519.      * Extract the offending TCP packet header.
  520.      */
  521.     hdr_len = ip->ip_hl << 2;
  522.     tcp = (struct tcphdr *) ((char *) ip + hdr_len);
  523.     data_len -= hdr_len;
  524.     if (data_len < offsetof(struct tcphdr, th_dport) + sizeof(tcp->th_dport)) {
  525.     remark("short TCP header in ICMP");
  526.     return;
  527.     }
  528.  
  529.     /*
  530.      * Process ICMP subcodes.
  531.      */
  532.     switch (icmp->icmp_code) {
  533.     case ICMP_UNREACH_NET:
  534.     case ICMP_UNREACH_PROTOCOL:
  535.     /* error("error: network or protocol unreachable"); */
  536.     /* NOTREACHED */
  537.     case ICMP_UNREACH_PORT:
  538.     case ICMP_UNREACH_HOST:
  539.     port = ntohs(tcp->th_dport);
  540.     for (sock = 0; sock < open_file_limit; sock++)
  541.         if (socket_to_port[sock] == port) {
  542.         report_and_drop_socket(sock, EHOSTUNREACH);
  543.         return;
  544.         }
  545.     break;
  546.     }
  547. }
  548.  
  549. /* do_send_string - send the send string */
  550.  
  551. do_send_string(sock)
  552. int     sock;
  553. {
  554.     char    buf[BUFSIZ];
  555.     char   *cp = buf;
  556.     char    ch;
  557.     int     c;
  558.     int     i;
  559.     char   *s = send_string;
  560.  
  561.     while (*s && cp < buf + sizeof(buf) - 1) {    /* don't overflow the buffer */
  562.  
  563.     if (*s != '\\') {            /* ordinary character */
  564.         *cp++ = *s++;
  565.     } else if (isdigit(*++s) && *s < '8') {    /* \nnn octal code */
  566.         sscanf(s, "%3o", &c);
  567.         *cp++ = c;
  568.         for (i = 0; i < 3 && isdigit(*s) && *s < '8'; i++)
  569.         s++;
  570.     } else if ((ch = *s++) == 0) {        /* at string terminator */
  571.         break;
  572.     } else if (ch == 'b') {            /* \b becomes backspace */
  573.         *cp++ = '\b';
  574.     } else if (ch == 'f') {            /* \f becomes formfeed */
  575.         *cp++ = '\f';
  576.     } else if (ch == 'n') {            /* \n becomes newline */
  577.         *cp++ = '\n';
  578.     } else if (ch == 'r') {            /* \r becomes carriage ret */
  579.         *cp++ = '\r';
  580.     } else if (ch == 's') {            /* \s becomes blank */
  581.         *cp++ = ' ';
  582.     } else if (ch == 't') {            /* \t becomes tab */
  583.         *cp++ = '\t';
  584.     } else {                /* \any becomes any */
  585.         *cp++ = ch;
  586.     }
  587.     }
  588.     write(sock, buf, cp - buf);
  589. }
  590.